import sys

class Overlap(Exception): pass

class Node:
    def __init__(self, left, bottom, right, up):
        self.bottom = bottom
        self.up = up
        self.left = left
        self.right = right
        self.xmid = (self.left+self.right)//2
        self.ymid = (self.bottom+self.up)//2
        self.full = self.bottom==self.up and self.left==self.right
        self.children = [None] * 4
        if self.left+1==self.right:
            self.children[0] = Node(0, 0, 0, 0)
            self.children[2] = Node(0, 0, 0, 0)
        if self.bottom+1==self.up:
            self.children[0] = Node(0, 0, 0, 0)
            self.children[1] = Node(0, 0, 0, 0)
    def add(self, left, bottom, right, up):
        if self.full: raise Overlap()
        if self.bottom==bottom and \
            self.up==up and \
            self.left==left and \
            self.right==right and \
            all(map(lambda child:child==None or (child.left==child.right and child.bottom==child.up), self.children)):
            self.full=True
            return
        # print(left, bottom, right, up, end=' ')
        if bottom<self.ymid:
            if left<self.xmid:
                # print("bottom left")
                if not self.children[0]: self.children[0]=Node(self.left, self.bottom, self.xmid, self.ymid)
                self.children[0].add(left, bottom, min(right,self.xmid), min(up,self.ymid))
            if right>self.xmid:
                # print("bottom right")
                if not self.children[1]: self.children[1]=Node(self.xmid, self.bottom, self.right, self.ymid)
                self.children[1].add(max(left,self.xmid), bottom, right, min(up,self.ymid))
        if up>self.ymid:
            if left<self.xmid:
                # print("top left")
                if not self.children[2]: self.children[2]=Node(self.left, self.ymid, self.xmid, self.up)
                self.children[2].add(left, max(self.ymid,bottom), min(self.xmid,right), up)
            if right>self.xmid:
                # print("top right")
                if not self.children[3]: self.children[3]=Node(self.xmid, self.ymid, self.right, self.up)
                self.children[3].add(max(self.xmid,left), max(self.ymid,bottom), right, up)
        self.full = all(map(lambda x:x!=None and x.full, self.children))

class Solution(object):
    def isRectangleCover(self, rectangles):
        bottom, up, left, right = sys.maxsize, -sys.maxsize, sys.maxsize, -sys.maxsize
        for l,b,r,u in rectangles:
            bottom = min(bottom, b)
            up = max(up, u)
            left = min(left, l)
            right = max(right, r)
        # print('BBox', left, bottom, right, up)
        root = Node(left, bottom, right, up)
        for l,b,r,u in rectangles:
            try:
                root.add(l,b,r,u)
            except Overlap as e:
                return False
        return root.full

print(Solution().isRectangleCover( [
  [1,1,3,3],
  [3,1,4,2],
  [1,3,2,4],
  [2,2,4,4]
]))